#
# do_migration migration_number
#     migration_number : 適用するマイグレーションの番号。
#                        現在適用されているマイグレーションから指定した番号まで順に適用する
#                        
require 'rubygems'
require 'mysql'
require 'activerecord'

require 'src/db_connect_info.rb'

# マイグレーションファイル名からクラス名へ変換する関数
def toClassName(filename)
  filename.sub(/^([0-9])+/, "").sub(/\.rb$/, "").gsub(/_([a-z])/){|matched| $1.upcase}.gsub(/_/, "")
end

# 現在の適用されているマイグレーション番号を取得する関数
def getCurrentMigrationNumber()
  numberFilePath = File.join(File.dirname(File.expand_path(__FILE__)), ".current")
  
  if(!File.exist?(numberFilePath)) then
    return 0
  end
  
  File.open(numberFilePath, "r") do |file|
    # TODO 整数に変換できない場合のエラー処理
    return file.gets.to_i
  end
end

# 指定したマイグレーション番号を持つマイグレーションファイルへのパスを返す
def getMigrationFilePath(number)
  Dir.chdir File.dirname(File.expand_path(__FILE__))
  number = format("%03d", number)
  migration_files = Dir.glob(number + "_*")
  if  (migration_files.length < 1) then
    Exception.new "指定されたマイグレーション番号" + number + "をもつファイルが見つかりません。"
  elsif(migration_files.length > 1) then
    Exception.new "指定されたマイグレーション番号" + number + "を持つファイルが複数見つかりました。¥nマイグレーションの適用を中止します。"
  end
  
  return migration_files[0]
end

# 現在のマイグレーション番号を保存する関数
def makeCurrentMigrationNumberFile(number)
  numberFilePath = File.join(File.dirname(File.expand_path(__FILE__)), ".current")
  File.open(numberFilePath, "w+") do |file|
    file.puts(number)
  end
end

# マイグレーションを適用する
def applyMigration(file_path, action) 
  require file_path
  
  className = toClassName(File.basename(file_path))
  migClass = eval(className)
  
  filename = File.basename(file_path)
  print "#{filename} の #{action} を適用します。\n"
  
  migClass.migrate(action)
end

DBConnectInfo.connect()

if($*.length != 1) then
  print "コマンド：\n    do_migration migration_number\n"
  return
end

cur_mig_number = getCurrentMigrationNumber()

migration_number = $*[0].to_i

begin
  if(cur_mig_number < migration_number) then
    
    print "マイグレーション番号を #{cur_mig_number} から #{migration_number} にします。\n"
    
    mig_file_path_array = Array.new()
    (cur_mig_number + 1).upto(migration_number) do |number|
      mig_file_path_array.push(getMigrationFilePath(number))
    end
    
    mig_file_path_array.each() do |file_path|
      applyMigration(file_path, :up)
      cur_mig_number = cur_mig_number + 1
    end
    
  elsif(cur_mig_number > migration_number) then
    mig_file_path_array = Array.new()
    cur_mig_number.downto(migration_number + 1) do |number|
      mig_file_path_array.push(getMigrationFilePath(number))
    end
    
    mig_file_path_array.each() do |file_path|
      applyMigration(file_path, :down)
      cur_mig_number = cur_mig_number - 1
    end
  else
    print "現在のマイグレーション番号と同じ番号が指定されています。\n"
  end
ensure
  makeCurrentMigrationNumberFile(cur_mig_number)
  print "現在のマイグレーション番号は #{cur_mig_number} です。"
end
